<?php

class XMLUtils
{
	private static $levels;
	
	public static function xmlNodeForDOMWithObject(&$dom, &$object)
	{
		$firstChildNode = $dom->createElement(get_class($object));
		
		foreach($object->columns as $key=>$value)
		{
			if (self::$levels > 1 || self::$levels == null)
			{
				$currentLevel = 1;
				
				if ($value instanceof ForeignKey)
				{
					self::processForeignKey($value, $dom, $firstChildNode, $currentLevel);
				}
				else if ($value instanceof ManyToMany)
				{
					self::processManyToMany($value, $dom, $firstChildNode, $currentLevel);
				}
			} 
			
			$childNode = $dom->createElement($key);
			
			if($value instanceof File)
			{
				if(stripslashes($value->value))
				{
					$path = $value->getPath();
					$childNode->appendChild($dom->createCDATASection($path.'/'.stripslashes($value->value)));
				}
			}
			else
			{
				$childNode->appendChild($dom->createCDATASection(stripslashes($value->value)));
			}
			
			$firstChildNode->appendChild($childNode);
				
			if ($value instanceof UnixTimestamp){
				self::formatUnixTimestamp($value, $dom, $firstChildNode);
			}
		}
		
		return $firstChildNode;
	}
	
	
	public static function objectToXML($object, $levels = 1)
	{
		//header('Content-Type: application/xml');
		//header('Cache-Control: no-store, must-revalidate');
		self::$levels = $levels;
		
		$dom               = new DOMDocument('1.0', 'UTF-8');
		$dom->formatOutput = true;
		$rootNode          = $dom->createElement('PHORM');
		
		self::$levels = $levels; 
		
		$node = self::xmlNodeForDOMWithObject($dom, $object);
		/*$firstChildNode    = $dom->createElement(get_class($object));
		foreach($object->columns as $key=>$value)
		{
			if (self::$levels > 1 || self::$levels == null)
			{
				$currentLevel = 1;
				
				if ($value instanceof ForeignKey)
				{
					self::processForeignKey($value, $dom, $firstChildNode, $currentLevel);
				}
				else if ($value instanceof ManyToMany)
				{
					self::processManyToMany($value, $dom, $firstChildNode, $currentLevel);
				}
			} 
			
			$childNode = $dom->createElement($key);
			
			if($value instanceof File)
			{
				if(stripslashes($value->value))
				{
					$path = $value->getPath();
					$childNode->appendChild($dom->createCDATASection($path.'/'.stripslashes($value->value)));
				}
			}
			else
			{
				$childNode->appendChild($dom->createCDATASection(stripslashes($value->value)));
			}
			
			$firstChildNode->appendChild($childNode);
				
			if ($value instanceof UnixTimestamp)
				self::formatUnixTimestamp($value, $dom, $firstChildNode);
		}*/
		
		$rootNode->appendChild($node);
		$dom->appendChild($rootNode);
		$dom->save('php://output');
	}
	
	public static function recordInformation($column, $value)
	{
		header('Content-Type: application/xml');
		//header('Pragma: no-cache');
		//header('Cache-Control: no-store, no-cache, must-revalidate');
		header('Cache-Control: no-store, must-revalidate');
		
		$dom               = new DOMDocument('1.0', 'UTF-8');
		$dom->formatOutput = true;
		$rootNode          = $dom->createElement('PHORM');
		
		$childNode = $dom->createElement('key');
		$childNode->appendChild($dom->createCDATASection($column));
		$rootNode->appendChild($childNode);
		
		$childNode = $dom->createElement('value');
		$childNode->appendChild($dom->createCDATASection($value));
		$rootNode->appendChild($childNode);
		
		$dom->appendChild($rootNode);
		
		// using the php output buffer uses less memory
		// than $dom->saveXML();
		$dom->save('php://output');
		//echo $dom->saveXML();
	}
	
	public static function queryToXML(Query $collection, $levels = null)
	{
		//header('Content-Type: application/xml');
		//header('Cache-Control: no-store, must-revalidate');
		
		//header('Pragma: no-cache');
		//header('Cache-Control: no-store, no-cache, must-revalidate');
		
		self::$levels = $levels; 
		
		$dom               = new DOMDocument('1.0', 'UTF-8');
		$dom->formatOutput = true;
		$rootNode          = $dom->createElement('PHORM');
		
		foreach($collection as $object)
		{
			$node = self::xmlNodeForDOMWithObject($dom, $object);
			
			// the code for xmlNodeForDOMWithObject(...) was right here.
			
			$rootNode->appendChild($node);
			$object->release();
		}
		
		$dom->appendChild($rootNode);
		
		// using the php output buffer uses less memory
		// than $dom->saveXML();
		$dom->save('php://output');
		//echo "Memory Usage: ".memory_get_peak_usage()/1000, "<br>";
		// this will use more memory:
		//echo $dom->saveXML();
	}
	
	private static function processManyToMany(ManyToMany &$object, &$dom, &$firstChildNode, $currentLevel)
	{
		if ($currentLevel) $currentLevel++;
		
		$records = $object->all();
		
		if ($records->length)
		{
			$childNode = $dom->createElement(get_class($records->getItemAt(0)));
			foreach ($records as $object)
			{
				$container = $dom->createElement(strtolower(get_class($object)));
			
				foreach($object->columns as $key=>$value)
				{
					if (!($value instanceof IIgnorableColumn) && !($value instanceof IJoinableColumn))
					{
						$related = $dom->createElement($key);
						
						if($value instanceof File)
						{
							if(stripslashes($value->value))
							{
								$path = $value->getPath();
								$related->appendChild($dom->createCDATASection($path.'/'.stripslashes($value->value)));
							}
						}
						else
						{
							$related->appendChild($dom->createCDATASection(stripslashes($value->value)));
						}
							
						//$related->appendChild($dom->createCDATASection(stripslashes($value->value)));
						
						$container->appendChild($related);
					}
					else 
					{
						if ($value instanceof ForeignKey && ($currentLevel < self::$levels || self::$levels == null))
						{
							self::processForeignKey($value, $dom, $childNode, $currentLevel);
						}
						else if ($value instanceof ManyToMany && ($currentLevel < self::$levels || self::$levels == null))
						{
							self::processManyToMany($value, $dom, $childNode, $currentLevel);
						}
					}
				}
			
				$childNode->appendChild($container);
				$object->release();
			}
		
			$firstChildNode->appendChild($childNode);
		}
	}
	
	private static function processForeignKey(ForeignKey &$object, &$dom, &$firstChildNode, $currentLevel)
	{
		if ($currentLevel) $currentLevel++;
		
		$childNode = $dom->createElement(get_class($object->relation));
		
		$attribute = $dom->createAttribute('value');
		$attribute->appendChild($dom->createTextNode($object->value));
		$childNode->appendChild($attribute);
		
		if ($currentLevel > 2)
		{
			$id = $object->value;
			$vo = new $object->relation();
			$vo->hydrateWithPrimaryKey($id);
			//$vo->initWithId($id);
		}
		else
		{
			$vo =& $object->relation;
		}
		
		foreach ($vo->columns as $key=>$value)
		{
			if (!($value instanceof IIgnorableColumn) && !($value instanceof IJoinableColumn))
			{
				$related = $dom->createElement($key);
				
				if($value instanceof File)
				{
					if(stripslashes($value->$key))
					{
						$path = $vo->getPath();
						$related->appendChild($dom->createCDATASection($path.'/'.stripslashes($value->$key)));
					}
				}
				else
				{
					$related->appendChild($dom->createCDATASection(stripslashes($vo->$key)));
				}
				//$related->appendChild($dom->createCDATASection(stripslashes($vo->$key)));
				
				$childNode->appendChild($related);
			}
			else
			{
				if ($value instanceof ForeignKey && ($currentLevel < self::$levels || self::$levels == null))
				{
					self::processForeignKey($value, $dom, $childNode, $currentLevel);
				}
				else if ($value instanceof ManyToMany && ($currentLevel < self::$levels || self::$levels == null))
				{
					self::processManyToMany($value, $dom, $childNode, $currentLevel);
				}
			}
			
			//if ($value instanceof UnixTimestamp)
				//self::formatUnixTimestamp($value, $dom, $childNode);
		}
		$vo->release();
		$firstChildNode->appendChild($childNode);
	}
	
	private static function formatUnixTimestamp(UnixTimestamp &$object, &$dom, &$firstChildNode)
	{
		$config = PhormConfig::getConfig();
		$childNode = $dom->createElement($object->column."_format");
		
		$childNode->appendChild($dom->createCDATASection(date($config->dateFormat, (int)$object->value)));
		$firstChildNode->appendChild($childNode);
	}
}
?>
